package com.dage.salesflow.excel;

import com.alibaba.excel.context.AnalysisContext;
import com.dage.salesflow.constant.ImportMode;
import com.dage.salesflow.constant.SysConstant;
import com.dage.salesflow.kit.DbKit;
import com.dage.salesflow.kit.Ret;
import com.jfinal.kit.StrKit;
import io.jboot.db.model.JbootModel;

import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * EXCEL导入工具类
 *
 * @param <EXCEL>  Excel模型类
 * @param <RECORD> 数据库实体类
 */
public class ExcelReader<EXCEL, RECORD extends JbootModel<RECORD>> {
	private final ExcelReaderChecker<RECORD> excelReaderChecker;
	private final ImportService<RECORD, EXCEL> importService;
	private final List<Ret> errors;
	private final boolean update;
	private final ImportMode mode;

	public ExcelReader(ExcelReaderChecker<RECORD> excelReaderChecker, ImportService<RECORD, EXCEL> importService, List<Ret> errors, ImportMode mode, boolean update) {
		this.excelReaderChecker = excelReaderChecker;
		this.importService = importService;
		this.errors = errors;
		this.mode = mode;
		this.update = update;
	}

	/**
	 * 存储数据库
	 *
	 * @param dataList   待导入的数据
	 * @param context    导入上下文
	 * @param updateList 待更新Record列表，方便使用，此方法完成后自动清空该列表，以便下一次调用
	 * @param insertList 待插入Record列表，方便使用，此方法完成后自动清空该列表，以便下一次调用
	 */
	public void saveData(List<ImportModel<EXCEL, RECORD>> dataList, AnalysisContext context, List<RECORD> updateList, List<RECORD> insertList) throws Exception {
		for (ImportModel<EXCEL, RECORD> importModel : dataList) {
			importService.onSheetProgress(importModel, context);
			Ret r = importService.setModelData(importModel, context);
			//严格模式直接失败
			if (mode == ImportMode.STRICT && !errors.isEmpty()) {
				return;
			}
			if (r.getCode() == SysConstant.IMPORT_ERROR) {
				errors.add(r);
				if (mode != ImportMode.SOFT) {
					continue;
				}
			}
			//处理null值，否则model更新会使用null覆盖原值
			Set<Map.Entry<String, Object>> attrsEntrySet = importModel.record._getAttrsEntrySet();
			Set<String> attrsDel = new HashSet<>();
			for (Map.Entry<String, Object> entry : attrsEntrySet) {
				if (entry.getValue() == null) {
					attrsDel.add(entry.getKey());
				}
			}
			for (String attr : attrsDel) {
				importModel.record.remove(attr);
			}

			if (update) {
				//覆盖更新模式
				Integer id = importService.queryId(importModel);
				if (id != null) {
					importService.setModelId(importModel.record, id);
					//更新校验
					Ret ret = excelReaderChecker.editCheck(importModel.record);
					if (ret.isOk()) {
						updateList.add(importModel.record);
						if (r.getCode() == SysConstant.IMPORT_WARN || !importModel.ret.isOk()) {
							if (StrKit.isBlank(r.getMsg())) {
								r.setMsg("");
							} else {
								r.setMsg(r.getMsg() + "<br/>");
							}
							if (StrKit.isBlank(importModel.ret.getMsg())) {
								importModel.ret.setMsg("");
							}
							Object data = r.getData();
							if (data == null) {
								data = importModel.ret.getData();
							}
							errors.add(new Ret(SysConstant.IMPORT_WARN, r.getMsg() + importModel.ret.getMsg(), data));
							if (mode == ImportMode.STRICT) {
								return;
							}
						}
					} else {
						errors.add(new Ret(SysConstant.IMPORT_ERROR, ret.getMsg(), importModel.rowIndex));
						if (mode == ImportMode.STRICT) {
							return;
						}
					}
				} else {
					insertData(insertList, importModel, r);
				}
			} else {
				//不是覆盖更新模式
				insertData(insertList, importModel, r);
			}
		}
		//严格模式直接失败
		if (mode == ImportMode.STRICT && !errors.isEmpty()) {
			return;
		}
		importService.beforeDbBatch(insertList, updateList);
		DbKit.batchListSave(insertList, DbKit.DB_BATCH_COUNT);
		DbKit.batchListUpdate(updateList, DbKit.DB_BATCH_COUNT);
	}

	private void insertData(List<RECORD> insertList, ImportModel<EXCEL, RECORD> importModel, Ret r) throws Exception {
		//插入校验
		Ret ret = excelReaderChecker.addCheck(importModel.record);
		if (ret.isOk()) {
			insertList.add(importModel.record);
			if (r.getCode() == SysConstant.IMPORT_WARN || !importModel.ret.isOk()) {
				if (StrKit.isBlank(r.getMsg())) {
					r.setMsg("");
				} else {
					r.setMsg(r.getMsg() + "<br/>");
				}
				if (StrKit.isBlank(importModel.ret.getMsg())) {
					importModel.ret.setMsg("");
				}
				Object data = r.getData();
				if (data == null) {
					data = importModel.ret.getData();
				}
				errors.add(new Ret(SysConstant.IMPORT_WARN, r.getMsg() + importModel.ret.getMsg(), data));
			}
		} else {
			errors.add(new Ret(SysConstant.IMPORT_ERROR, ret.getMsg(), importModel.rowIndex));
		}
	}


}
